package com.shenhangye.pushlive.codec

import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.media.MediaMuxer
import android.util.Log
import android.view.Surface
import com.shenhangye.pushlive.util.FileUtils
import java.io.File

class VideoEncoderCore(width: Int, height: Int, bitRate: Int, outPutFile: File) {
    private val MIME_TYPE: String =MediaFormat.MIMETYPE_VIDEO_AVC
    private var mBufferInfo: MediaCodec.BufferInfo? = null
    private val IFRAME_INTERVAL: Int = 5
    private val FRAME_RATE: Int = 30
    var mEncoder:MediaCodec?=null
    private var mInputSurface: Surface? = null
    private var mMuxer: MediaMuxer? = null
    private var mTrackIndex = 0
    private var mMuxerStarted = false


    fun getInputSurface():Surface?=mInputSurface;


    fun drainEncoder(endOfStream:Boolean){
        val TIMEOUT_USEC=10000L;

        if (endOfStream){
            mEncoder?.signalEndOfInputStream();
        }

        var index=0
        var encoderOutputBuffers=mEncoder?.getOutputBuffer(index)
        while (true){
            var encoderStatus=mEncoder?.dequeueOutputBuffer(mBufferInfo!!,TIMEOUT_USEC);
            when(encoderStatus){
                MediaCodec.INFO_TRY_AGAIN_LATER->{
                    if (endOfStream){

                    }else{
                        break
                    }
                }
                MediaCodec.INFO_OUTPUT_FORMAT_CHANGED->{
                    encoderOutputBuffers=mEncoder?.getOutputBuffer(index)
                }
                else->{
                    if (encoderStatus!! <0){

                    }else{
                        val encodedData = mEncoder?.getOutputBuffer(encoderStatus)
                        val data = mBufferInfo?.size?.let { ByteArray(it) }
                        encodedData?.get(data)
                        FileUtils.writeBytes(data)
                        data?.let { FileUtils.writeContent(it) }
//                        if ((mBufferInfo?.flags?.and(MediaCodec.BUFFER_FLAG_CODEC_CONFIG))!=0){
//                            mBufferInfo!!.size = 0
//                        }

//                        if (mBufferInfo?.size!=0){
//                            mBufferInfo?.offset?.let { encodedData?.position(it) };
//                            encodedData!!.limit(mBufferInfo!!.offset + mBufferInfo!!.size)
//                        }
                    }

                    mEncoder?.releaseOutputBuffer(encoderStatus, false)
                    if ((mBufferInfo!!.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        if (!endOfStream) {
                            Log.w(TAG, "reached end of stream unexpectedly")
                        } else {
//                            if (VideoEncoderCore.VERBOSE) Log.d(
//                                VideoEncoderCore.TAG,
//                                "end of stream reached"
//                            )
                        }
                        break // out of while
                    }
                }
            }
        }
    }
    private  val TAG = "VideoEncoderCore"

    /**
     * Releases encoder resources.
     */
    fun release() {
//        if (VERBOSE) Log.d(VideoEncoderCore.TAG, "releasing encoder objects")
        if (mEncoder != null) {
            mEncoder!!.stop()
            mEncoder!!.release()
            mEncoder = null
        }
        if (mMuxer != null) {
            // TODO: stop() throws an exception if you haven't fed it any data.  Keep track
            //       of frames submitted, and don't call stop() if we haven't written anything.
            mMuxer!!.stop()
            mMuxer!!.release()
            mMuxer = null
        }
    }

    init {
        mBufferInfo=MediaCodec.BufferInfo()
        var format=MediaFormat.createVideoFormat(MIME_TYPE,width,height)
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
        format.setInteger(MediaFormat.KEY_BIT_RATE,bitRate)
        format.setInteger(MediaFormat.KEY_FRAME_RATE,FRAME_RATE)
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,IFRAME_INTERVAL)
        mEncoder=MediaCodec.createEncoderByType(MIME_TYPE)
        mEncoder?.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE)
        mInputSurface=mEncoder?.createInputSurface()
        mEncoder?.start()
        mMuxer=MediaMuxer(outPutFile.toString(),MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
        mTrackIndex = -1
        mMuxerStarted = false
    }
}